package cn.peach.pay.service.impl;

import cn.peach.basic.exception.MyException;
import cn.peach.order.domain.OrderPet;
import cn.peach.order.domain.OrderPetDetail;
import cn.peach.order.mapper.OrderPetDetailMapper;
import cn.peach.order.mapper.OrderPetMapper;
import cn.peach.pay.domain.PayAlipayInfo;
import cn.peach.pay.domain.PayBill;
import cn.peach.pay.domain.PayFlow;
import cn.peach.pay.dto.AlipayNotifyDto;
import cn.peach.pay.mapper.PayAlipayInfoMapper;
import cn.peach.pay.mapper.PayBillMapper;
import cn.peach.pay.mapper.PayFlowMapper;
import cn.peach.pay.service.IPayService;
import cn.peach.pet.domain.Pet;
import cn.peach.pet.mapper.PetMapper;
import com.alibaba.fastjson.JSON;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Transactional
public class PayServiceImpl implements IPayService {

    @Autowired
    private PayAlipayInfoMapper alipayInfoMapper;
    @Autowired
    private PayBillMapper payBillMapper;
    @Autowired
    private PayFlowMapper payFlowMapper;
    @Autowired
    private OrderPetMapper orderPetMapper;
    @Autowired
    private OrderPetDetailMapper orderPetDetailMapper;
    @Autowired
    private PetMapper petMapper;

    @Override
    public String applyPay(String orderNo) {
        // 判断订单号是否为空
        if (!StringUtils.isEmpty(orderNo)) {
            throw new MyException("请求错误");
        }
        // 加载支付宝配置
        PayAlipayInfo alipayInfo = alipayInfoMapper.getFirst();
        if (null == alipayInfo) {
            throw new MyException("支付宝配置错误");
        }
        // 查询支付单
        PayBill payBill = payBillMapper.getByNo(orderNo);
        if (null == payBill) {
            throw new MyException("支付单错误");
        }
        // 发起支付请求 支付宝文档 全局设置的一次参数
        Factory.setOptions(alipayInfo.getOptions());
        try {
            // API调用  电脑网站
            String returnUrl = String.format(alipayInfo.getReturnUrl(), orderNo);
            AlipayTradePagePayResponse response = Factory.Payment.Page()
                    .pay(payBill.getDigest(), payBill.getUnionPaySn(), payBill.getMoney().toString(), returnUrl);
            // 获取返回体
            System.out.println(response.body);
            if (ResponseChecker.success(response)) {
                return response.body;
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("调用失败原因" + e.getMessage());
            throw new RuntimeException(e.getMessage(),e);
        }
        return "---0.0---";
    }

    /**
     * 支付结果的处理
     * 检验参数
     * 验证签名
     * 防止结果重复处理（防重 幂等性处理）
     * 保存支付流水PayFlow
     * 修改支付单状态PayBill和业务单状态
     * 如果支付失败需要退回宠物库存
     *
     * @param dto
     * @return
     */
    @Override
    public String alipayNotify(AlipayNotifyDto dto) {
        /**把结果DTO转成HashMap用作签名参数
        接收到的所有参数放入一个Map中*/
        // 把对象转成JSON字符串
        String jsonString = JSON.toJSONString(dto);
        // json字符串转Map
        Map<String, String> map = JSON.parseObject(jsonString, Map.class);

        // 支付宝配置
        PayAlipayInfo alipayInfo = alipayInfoMapper.getFirst();
        try {
            Boolean notify = Factory.Payment.Common().verifyNotify(map);
            if (! notify) {
                System.out.println("验证签名是卵的");
                return "卵的";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 验证订单号 金额是否一致
        String out_trade_no = dto.getOut_trade_no();
        if (! StringUtils.isEmpty(out_trade_no)) {
            System.out.println("无效单号");
            return "卵的单号";
        }
        PayBill payBill = payBillMapper.getByNo(out_trade_no);
        if (payBill == null) {
            System.out.println("错误的单号");
            return "卵单";
        }
        // 防重处理
        if (payBill.getState().intValue() != PayBill.SATET_WAIT_PAY) {
            // 不相等说明支付已被处理
            System.out.println("订单被处理了");
            return "success";
        }
        BigDecimal decimal = new BigDecimal(dto.getTotal_amount());
        if (payBill.getMoney().compareTo(decimal) != 0) {
            System.out.println("假钱，拒收");
            return "fail";
        }
        // 保存支付流水
        PayFlow payFlow = new PayFlow();
        BeanUtils.copyProperties(dto, payFlow);
        payFlowMapper.add(payFlow);
        // 修改支付订单状态
        if (dto.isTradeWit()) {
            System.out.println("正在支付000");
        }
        /**
         * 业务单的处理
         */
        OrderPet orderPet = orderPetMapper.getByOrderNo(out_trade_no);
        if (orderPet == null) {
            System.out.println("业务单号错误");
            return "fail";
        }
        // 订单明细
        List<OrderPetDetail> details = orderPetDetailMapper.getByOrderNo(out_trade_no);
        // 拿到宠物id
        List<Long> petIds = details.stream().map(detail -> detail.getPetId()).collect(Collectors.toList());
        // 查询所有上架的宠物
        List<Pet> pets = petMapper.patchSelectById(petIds, Pet.STATE_ONLINE);
        // 支付状态判断处理
        if (dto.isTradeSuccess()) {
            // 成功支付
            payBill.setState(PayBill.SATET_SUCCESS_PAY);
            // 成功支付代发货
            orderPet.setState(OrderPet.STATE_SUCCESS_PAY);
        }else if(dto.isTradeExpire()){
            // 支付状态超时
            payBill.setState(PayBill.SATET_OUTTIME_OR_RETURN);
            orderPet.setState(OrderPet.STATE_PAY_OUTTIME_CANCEL);
            // 如果订单支付 宠物仓库就要退回
            pets.forEach(pet -> {
                // +1是因为宠物只能被购买一次 退回也就只有一次
                pet.setStore_number(pet.getStore_number() + 1);
                petMapper.update(pet);
            });
        }else {
            System.out.println("其他交易状态");
            return "fail";
        }
        // 最后支付处理时间
        payBill.setLastPayTime(new Date());
        payBillMapper.update(payBill);
        orderPetMapper.update(orderPet);
        return "success";
    }
}
